module Pedido (Pedido, nuevoP, numeroP, atendioP, combosP, dificultadP, agregarComboP, anularComboP, cambiarBebidaComboP, elMezcladitoP)
	where

import Tipos
import Combo

data Pedido = P Int Empleado | AgregarCombo Combo Pedido deriving (Show,Eq)

nuevoP :: Int -> Empleado -> [Combo] -> Pedido
nuevoP n e [] = P n e
nuevoP n e (c:cs) = AgregarCombo c (nuevoP n e cs)

numeroP :: Pedido -> Int
numeroP (P n e) = n 
numeroP (AgregarCombo c p) = numeroP p 

atendioP :: Pedido -> Empleado
atendioP (P n e) = e
atendioP (AgregarCombo c p) = atendioP p

combosP :: Pedido -> [Combo]
combosP (P n e) = []
combosP (AgregarCombo c p)= c: (combosP p)

dificultadP :: Pedido -> Energia
dificultadP (P n e) = 0
dificultadP (AgregarCombo c p)= (dificultadC c) + (dificultadP p)

agregarComboP :: Pedido -> Combo -> Pedido
agregarComboP (P n e) c = (AgregarCombo c (P n e))
agregarComboP (AgregarCombo cs p) c = AgregarCombo cs (agregarComboP p c)

anularComboP :: Pedido -> Int -> Pedido
anularComboP ped i = anulacion ped ped i

--aux
anulacion :: Pedido -> Pedido -> Int -> Pedido
anulacion (P n e) _ _ = (P n e)
anulacion (AgregarCombo c p) ped i 
	|posicion (AgregarCombo c p) ped == i = p
	|otherwise = AgregarCombo c (anulacion p ped i)

--aux
posicion :: Pedido -> Pedido -> Int
posicion (AgregarCombo c (P n e)) ped = totalDeCombos ped - 1
posicion (AgregarCombo c p) ped = posicion p ped - 1

--aux
totalDeCombos :: Pedido -> Int
totalDeCombos p = length (combosP p)


cambiarBebidaComboP :: Pedido -> Bebida -> Int -> Pedido
cambiarBebidaComboP ped beb i = cambioDeBebida ped ped beb i

--aux
cambioDeBebida :: Pedido -> Pedido -> Bebida -> Int -> Pedido
cambioDeBebida (P n e) ped beb i = (P n e)
cambioDeBebida (AgregarCombo c p) ped b i 
	|posicion (AgregarCombo c p) ped == i = (AgregarCombo (cambiarBebida c b) p)
	|otherwise = AgregarCombo c (cambioDeBebida p ped b i)

--aux					
cambiarBebida :: Combo -> Bebida -> Combo
cambiarBebida c b1  = nuevoC b1 (sandwichC c) (dificultadC c) 					

--aux
cambiarSanguche :: Combo -> Hamburguesa -> Combo
cambiarSanguche c h1 = nuevoC (bebidaC c) h1 (dificultadC c)

--aux
cantAparicionesC :: Combo -> Pedido -> Int
cantAparicionesC _ (P n e) = 0
cantAparicionesC combo (AgregarCombo c p)
	|(sandwichC combo == sandwichC c && bebidaC combo == bebidaC c) = 1 + cantAparicionesC combo p
	|otherwise = cantAparicionesC combo p				


elMezcladitoP :: Pedido -> Pedido
elMezcladitoP (AgregarCombo combo pedido) = elMezcladito' (AgregarCombo combo pedido) (AgregarCombo combo pedido) (P (numeroP pedido) (atendioP pedido))

--aux
elMezcladito' :: Pedido -> Pedido -> Pedido -> Pedido
elMezcladito' (P n e) mismoPedido loQueSeAgrego = (P n e)
elMezcladito' (AgregarCombo combo pedido) mismoPedido loQueSeAgrego
	|seRepiteC combo (AgregarCombo combo pedido) = elMezcladito' modificaPrimerComboDelPedido mismoPedido loQueSeAgrego
	|otherwise = (AgregarCombo combo (elMezcladito' pedido mismoPedido (AgregarCombo combo loQueSeAgrego)))
	
	where 	modificaPrimerComboDelPedido = (AgregarCombo (cambiarLoNecesario (AgregarCombo combo pedido) (AgregarCombo combo pedido) loQueSeAgrego (primerasApariciones (bebidasDelPedido mismoPedido)) (primerasApariciones (sanguchesDelPedido mismoPedido)) mismoPedido) pedido)
	

--aux
cambiarLoNecesario :: Pedido -> Pedido -> Pedido ->[Bebida] -> [Hamburguesa] -> Pedido ->  Combo
cambiarLoNecesario (AgregarCombo c p) ped2 loQueSeAgrego (b:bs) (h:hs) pedido
	|seRepiteEnPedidoOEstaAgregadoB = buscoOtraBedida
	|otherwise = cambiarBebida c b
	
	where	seRepiteEnPedidoOEstaAgregadoB = (seRepiteC (cambiarBebida c b) pedido) || (estaCombo (cambiarBebida c b) loQueSeAgrego)
		buscoOtraBedida	= (cambiarLoNecesario (AgregarCombo c p) ped2 loQueSeAgrego bs (h:hs) pedido)

cambiarLoNecesario ped (AgregarCombo c p) loQueSeAgrego [] (h:hs) pedido
	|seRepiteEnPedidoOEstaAgregadoH = buscoOtroSanguche
	|otherwise = cambiarSanguche c h
	
	where	buscoOtroSanguche = (cambiarLoNecesario ped (AgregarCombo c p) loQueSeAgrego [] hs pedido)
		seRepiteEnPedidoOEstaAgregadoH = (seRepiteC (cambiarSanguche c h) pedido) || (estaCombo (cambiarSanguche c h) loQueSeAgrego)
              

--aux
estaCombo :: Combo -> Pedido -> Bool
estaCombo combo (P n e) = False
estaCombo combo (AgregarCombo c p) = (cantAparicionesC combo (AgregarCombo c p)) == 1

--aux
bebidasDelPedido :: Pedido -> [Bebida]
bebidasDelPedido (P n e) = []
bebidasDelPedido (AgregarCombo c p) = bebidaC c : bebidasDelPedido p

--aux
sanguchesDelPedido :: Pedido -> [Hamburguesa]
sanguchesDelPedido (P n e) = []
sanguchesDelPedido (AgregarCombo c p) = sandwichC c : sanguchesDelPedido p

--aux
seRepiteC :: Combo -> Pedido -> Bool
seRepiteC combo (P n e) = False
seRepiteC combo (AgregarCombo c p) = (cantAparicionesC combo (AgregarCombo c p))>1

--Aux
primerasApariciones :: Eq a => [a] -> [a]
primerasApariciones lista = primerasApariciones' [] lista

--Aux
primerasApariciones' :: Eq a => [a] -> [a] -> [a]
primerasApariciones' xs [] = xs
primerasApariciones' xs (y:ys)
	|elem y xs == False = primerasApariciones' (xs++[y]) ys
	|otherwise = primerasApariciones' xs ys

